(module statements (lib "eopl.ss" "eopl")
  
  (require "drscheme-mp5-init.scm")

  (require "lang.scm")
  (require "data-structures.scm")
  (require "environments.scm")
  (require "store.scm")
  (require "interp.scm")
  

  
;;;;;;;;;;;;;;;; the interpreter ;;;;;;;;;;;;;;;;
  
(define execute-program!
  (lambda (pgm)
    (initialize-store!)
    (cases program pgm
      (a-program (statement)
        (execute-statement! statement (init-env))))))

(define execute-statement!
  (lambda (stmt env)
    (cases statement stmt
      (assign-statement (id exp)
        (setref!
          (apply-env env id)
          (value-of exp env)))
      (compound-statement (statements)
        (for-each
          (lambda (statement)
            (execute-statement! statement env))
          statements))
      (print-statement (exp)
        (logged:printf "~s~%" (value-of exp env)))
      (if-statement (exp true-statement false-statement)
        (if (expval->bool (value-of exp env))
          (execute-statement! true-statement env)
          (execute-statement! false-statement env)))
      (block-statement (ids statement)
        (execute-statement! statement
          (extend-env ids
            (map
              (lambda (d) (newref '*uninitialized*))
              ids)
            env)))
      )))
)  

;; Examples:

;; (run "var x,y; {x = 3; y = 4; print +(x,y)}")    % Example 1
;; 7
;; (run "var x,y,z; {x = 3; y = 4; z = 0;           % Example 2
;;                    while not(zero?(x)) 
;;                      {z = +(z,y); x = -(x,1)};
;;                    print z}")
;; 12
;; (run " var x; {x = 3; print x;                   % Example 3
;;                 var x; {x = 4; print x};  
;;                 print x}")
;; 3
;; 4
;; 3
;; (run "var f,x; {f = proc(x,y) *(x,y);            % Example 4
;;                  x = 3;
;;                  print (f 4 x)}")
;; 12


